package com.joysuch.wwyt.bp.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joysuch.wwyt.bp.bean.investigate.SimpleTaskAssign;
import com.joysuch.wwyt.bp.entity.BpInvestigateTaskAssign;
import com.joysuch.wwyt.bp.entity.BpInvestigateTaskHis;
import com.joysuch.wwyt.bp.entity.BpInvestigateTaskSummary;
import com.joysuch.wwyt.bp.entity.dto.DeleteInvestigateRecordDto;
import com.joysuch.wwyt.bp.mapper.BpInvestigateTaskAssignMapper;
import com.joysuch.wwyt.bp.mapper.BpSummaryStatMapper;
import com.joysuch.wwyt.bp.service.BpInvestigateRecordService;
import com.joysuch.wwyt.bp.service.BpInvestigateTaskAssignService;
import com.joysuch.wwyt.bp.service.BpInvestigateTaskHisService;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jwk
 * @since 2021-09-16
 */
@Slf4j
@Service
public class BpInvestigateTaskAssignServiceImpl extends ServiceImpl<BpInvestigateTaskAssignMapper, BpInvestigateTaskAssign> implements BpInvestigateTaskAssignService {

    @Autowired
    private RedisClient redisClient;

    @Autowired
    BpInvestigateTaskAssignMapper mapper;

    @Autowired
    BpInvestigateTaskHisService bpInvestigateTaskHisService;

    @Autowired
    BpInvestigateTaskAssignService bpInvestigateTaskAssignService;

    @Autowired
    BpInvestigateRecordService bpInvestigateRecordService;

    @Autowired
    BpSummaryStatMapper summaryStatMapper;

    // 数据清除完毕的标识
    private static final String CLEAR_TASK_ASSIGN_HIS_OVER_FLAG = "clearTaskAssignHisOver";
    // 上一个taskId
    private static final String CLEAR_TASK_ASSIGN_HIS_LAST_TASK_ID = "clearTaskAssignHisLastTaskId";
    // 上一条recordId
    private static final String CLEAR_TASK_ASSIGN_HIS_LAST_RECORD_ID = "clearTaskAssignHisLastRecordId";


    public List<Long> getUserIdsByTaskId(Long id) {
        if (id != null) {
            return mapper.findUserIdsByTaskId(id);
        }
        return null;
    }

    @Override
    public List<SimpleTaskAssign> getByTaskIds(List<Long> taskIds) {
        return mapper.selectSimpleAssignByTaskIds(taskIds);
    }

    @Override
    public List<SimpleTaskAssign> getUserIdByTaskIds(List<Long> taskIds) {
        return mapper.selectUserByTaskIds(taskIds);
    }

    @Override
    public List<SimpleTaskAssign> getHistoryUserIdByTaskIds(List<Long> taskIds) {
        return mapper.selectHistoryUserByTaskIds(taskIds);
    }

    @Override
    public long deleteByIds(List<Long> ids) {
        return mapper.deleteByIds(ids);
    }

    @Override
    public Integer findAssignsCount(Long taskId) {
        return mapper.findAssignsCount(taskId);
    }

    @Override
    public void deleteByTaskIdsAndUserIdNe(List<Long> taskIds, Long currentUserId) {
        mapper.deleteByTaskIdsAndUserIdNe(taskIds, currentUserId);
    }

    /**
     * 定时任务删除taskAssignHis表数据
     * 0 0/5 2-5 * * ?   凌晨2点到5点, 每5分钟执行一次
     */
    // @Scheduled(cron = "0/5 * * * * ?")
    @Override
    public void clearInvestigateTaskAssignHis() {
        if (redisClient.get(CLEAR_TASK_ASSIGN_HIS_OVER_FLAG) != null) {
//            log.info("======== taskAssign已清除完毕.");
            return;
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("======== 查询sourceType = 0的任务");
        String str1 = redisClient.get(CLEAR_TASK_ASSIGN_HIS_LAST_TASK_ID);
        Long lastTaskId = StringUtil.isEmpty(str1) ? null : Long.valueOf(str1);
        // 查询taskHis表source_type = 0 且 status=被完成, id正序查询3000条
        // 查询到task_id和user_id, 直接再去taskAssignHis表进行删除操作即可
        List<BpInvestigateTaskHis> oldSourceTask = bpInvestigateTaskHisService.getFinishOldSourceTask(lastTaskId);
        stopWatch.stop();
        log.info("======== {}, 总条数: {}, 耗时: {}ms", stopWatch.getLastTaskName(), CollectionUtils.isEmpty(oldSourceTask) ? 0 : oldSourceTask.size(), stopWatch.getLastTaskTimeMillis());

        if (CollectionUtils.isNotEmpty(oldSourceTask)) {
            // 取最后一条记录id缓存, 下次只查询大于此id的任务
            BpInvestigateTaskHis bpInvestigateTaskHis = oldSourceTask.get(oldSourceTask.size() - 1);
            if (bpInvestigateTaskHis != null) {
                redisClient.set(CLEAR_TASK_ASSIGN_HIS_LAST_TASK_ID, String.valueOf(bpInvestigateTaskHis.getId()));
            }
            stopWatch.start("删除sourceType = 0的task_assign_his数据");
            mapper.deleteByTaskIdAndUserId(oldSourceTask);
            stopWatch.stop();
            log.info("======== {}, 耗时: {}ms", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());
        }

        stopWatch.start("======== 查询sourceType = 1的任务");
        String str2 = redisClient.get(CLEAR_TASK_ASSIGN_HIS_LAST_RECORD_ID);
        Long lastRecordId = StringUtil.isEmpty(str2) ? null : Long.valueOf(str2);
        // 查询record_his表task_id,check_user_id, sourceType = 1 且 check_result != '未检' 且 check_user_id != -1, id正序查询3000条
        // 再去taskAssignHis表匹配task_id的值相等的且user_id != check_user_id 的数据进行删除
        List<DeleteInvestigateRecordDto> newSourceTask = bpInvestigateRecordService.getFinishNewSourceTask(lastRecordId);
        stopWatch.stop();
        log.info("======== {}, 总条数: {}, 耗时: {}ms", stopWatch.getLastTaskName(), CollectionUtils.isEmpty(newSourceTask) ? 0 : newSourceTask.size(), stopWatch.getLastTaskTimeMillis());

        if (CollectionUtils.isNotEmpty(newSourceTask)) {
            DeleteInvestigateRecordDto dto = newSourceTask.get(newSourceTask.size() - 1);
            if (dto != null) {
                redisClient.set(CLEAR_TASK_ASSIGN_HIS_LAST_RECORD_ID, String.valueOf(dto.getId()));
            }
            stopWatch.start("删除sourceType = 1的task_assign_his数据");
            mapper.deleteByTaskIdAndUserIdNe(newSourceTask);
            stopWatch.stop();
            log.info("======== {}, 耗时: {}ms", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());
        }

        log.info("======== 清除taskAssignHis, 总耗时: {}ms", stopWatch.getTotalTimeMillis());

        if (CollectionUtils.isEmpty(oldSourceTask) && CollectionUtils.isEmpty(newSourceTask)) {
            redisClient.set(CLEAR_TASK_ASSIGN_HIS_OVER_FLAG, "1");
            recalculateStatCount(stopWatch);
        }
    }

    public void recalculateStatCount(StopWatch stopWatch) {
        log.info("======开始整理隐患排查统计数据========");
        BpInvestigateTaskSummary firstSummary = summaryStatMapper.getFirstSummary();
        Date firstSummaryDate = Objects.nonNull(firstSummary) ? firstSummary.getCheckDate() : null;
        Date start = new Date();
        Date end = DateUtil.offsetDay(start, -1);
        SimpleDateFormat dateFormat = SimpleDateFormatCache.getYmd();
        do {
            String startStr = dateFormat.format(start);
            String endStr = dateFormat.format(end);
            stopWatch.start(String.format("===== 历史任务总数整理：%s - %s", startStr, endStr));
            summaryStatMapper.hisTaskCount(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            stopWatch.start(String.format("===== 运行时任务总数整理：%s - %s", startStr, endStr));
            summaryStatMapper.runTaskCount(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            stopWatch.start(String.format("===== 历史任务完成数整理：%s - %s", startStr, endStr));
            summaryStatMapper.hisTaskDoneCount(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            stopWatch.start(String.format("===== 运行时任务完成数整理：%s - %s", startStr, endStr));
            summaryStatMapper.runTaskDoneCount(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            stopWatch.start(String.format("===== 历史任务异常数整理：%s - %s", startStr, endStr));
            summaryStatMapper.hisExceptionCount(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            stopWatch.start(String.format("===== 运行时任务异常数整理：%s - %s", startStr, endStr));
            summaryStatMapper.runExceptionCount(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            stopWatch.start(String.format("===== 计划性隐患排查历史数据整理：%s - %s", startStr, endStr));
            summaryStatMapper.planndSummaryHis(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            stopWatch.start(String.format("===== 计划性隐患排查运行时数据整理：%s - %s", startStr, endStr));
            summaryStatMapper.planndSummary(start, end);
            stopWatch.stop();
            log.info("{} 耗时： {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());

            start = end;
            end = DateUtil.offsetDay(start, -1);

        }while (Objects.nonNull(firstSummaryDate) && start.after(firstSummaryDate));
    }

}
